//---------------------------------------------------------------------------
/**
 * \class CSpace
 * \brief This is a space class to by store (key,value) pairs.
 * \version 0.1
 *
 * \author Woo-Hyun Kim (woorung@nhncorp.com, woorung@gmail.com)
 * \author http://blog.naver.com/wisereign .
 *
 * \date 2007/09/04
 */
//---------------------------------------------------------------------------
#ifndef CSpaceH
#define CSpaceH
//-----------------------------------------------------------------
#include <iostream>
#include <iterator>
#include <string>
#include <deque>
#include <vector>
#include <map>

#include <time.h>
#include <limits.h>
//----------------------------------------------------------------
#include "CSmartTemplate.h"
#include "CObject.h"
//----------------------------------------------------------------
// lock file path
#define DEFAULT_SPACE_LOCK_FILE_PATH "/tmp/"
// ttl info (unit = sec.)
#define MAX_TTL LONG_MAX
//----------------------------------------------------------------
using namespace std;
//----------------------------------------------------------------
// Remark:
// 1. In order to manage the deque container, CSpace internally
//    uses copy constructor, assign constructor, clone(), and comparison operator.
//    Therefore, containing CObject and its derived classes must
//    implement those kinds of functions.
// 2. The read() and take() return a pointer to newly allocated instances.
//    Finally, the returned instance must be released by users.
//----------------------------------------------------------------
class CSpace {
private:
	string space_name;
	string lock_file;
	//map<string, deque< CSmartTemplate<CObject> > * > spaces;
	deque< CSmartTemplate<CObject> > space;

	// for synchronization
	pthread_mutex_t space_mutex;
	pthread_cond_t space_cond;

	// ------------------------
	// get a reference from container, and then its changes can be influenced on the container
	// # Remark : it must be used in mutex blocks because of some changes of container own itself
	// ------------------------
	CObject *lookup(CObject *key, CObject *obj);
	// ------------------------

public:
        CSpace(char *name);
        virtual ~CSpace();

	int clear();
	int write(CObject *obj);
	int write(CObject *obj, time_t ttl);
	int write(CObject *key, CObject *obj);
	int write(CObject *key, CObject *obj, time_t ttl);
	CObject *read(CObject *obj);
	CObject *read(CObject *key, CObject *obj);
	vector< CSmartTemplate<CObject> > &read(CObject *key, size_t read_limit, vector< CSmartTemplate<CObject> > &objs);
	CObject *readIfExists(CObject *obj);
	CObject *readIfExists(CObject *key, CObject *obj);
	vector< CSmartTemplate<CObject> > &readIfExists(CObject *key, size_t read_limit, vector< CSmartTemplate<CObject> > &objs);
	CObject *take(CObject *obj);
	CObject *take(CObject *key, CObject *obj);
	vector< CSmartTemplate<CObject> > &take(CObject *key, size_t take_limit, vector< CSmartTemplate<CObject> > &objs);
	CObject *takeIfExists(CObject *obj);
	CObject *takeIfExists(CObject *key, CObject *obj);
	vector< CSmartTemplate<CObject> > &takeIfExists(CObject *key, size_t take_limit, vector< CSmartTemplate<CObject> > &objs);

	int size();
	void list();

	int purge();

	int save();
	int load();
};
#endif
